package org.streets.workflow.engine.mem;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.streets.workflow.engine.ISyncRouter;
import org.streets.workflow.engine.event.INodeEventListener;
import org.streets.workflow.engine.plugin.INodeNetExtension;
import org.streets.workflow.model.net.WFSyncRouter;

/**
 * 
 */
public class SyncRouter extends AbstractNode implements ISyncRouter {

    public transient static final Log log = LogFactory.getLog(SyncRouter.class);
    public transient static final String Extension_Target_Name = "org.fireflow.kernel.SynchronizerInstance";
    public transient static List<String> Extension_Point_Names = new ArrayList<String>();
    public transient static final String Extension_Point_NodeInstanceEventListener = "NodeInstanceEventListener";


    static {
        Extension_Point_Names.add(Extension_Point_NodeInstanceEventListener);
    }

    private int volume = 0;// 即节点的容量
    
    private transient WFSyncRouter routerModel = null;

    public SyncRouter(WFSyncRouter model) {
        this.routerModel = model;
        int a = routerModel.getEnteringTransitions().size();
        int b = routerModel.getLeavingTransitions().size();
        this.volume = a * b;
        this.type = NodeType.Router;
    }
    
    public String getNodeId() {
        return this.routerModel.getId();
    }

    @SuppressWarnings("unchecked")
    public WFSyncRouter getNodeModel() {
        return this.routerModel;
    }

//    /* (non-Javadoc)
//     * @see org.fireflow.kernel.INodeInstance#fire(org.fireflow.kernel.IToken)
//     */
//    public void fire(IToken tk) throws WorkflowException {
//        //TODO 此处性能需要改善一下,20090312
//        IJoinPoint joinPoint = null;
//        synchronized (this) { //流程同步器需要处理并发的情况，而activity的节点不需要处理并发情况？同步器节点，可能被同时触发，activity节点不会被同时触发？
//            tk.setNodeId(this.getSynchronizer().getId());
//            log.debug("The weight of the Entering TransitionInstance is " + tk.getValue());
//            // 触发TokenEntered事件
//            NodeEvent event1 = new NodeEvent(this);
//            event1.setToken(tk);
//            event1.setEventType(NodeEvent.NODEINSTANCE_TOKEN_ENTERED);//token 进入
//            fireNodeEvent(event1);
//
//            //汇聚检查
//
//            joinPoint = ((ProcessInstance) tk.getCurrentProcessInstance()).createJoinPoint(this, tk);// JoinPoint由谁生成比较好？
//            int value = joinPoint.getValue();
//            log.debug("The volume of " + this.toString() + " is " + volume);
//            log.debug("The value of " + this.toString() + " is " + value);
//            if (value > volume) {//如果value大于同步器容量，那说明出错了
//            	WorkflowException exception = new WorkflowException(tk.getCurrentProcessInstance(),
//                        this.getSynchronizer(),
//                        "Error:The token count of the synchronizer-instance can NOT be  greater than  it's volumn  ");
//                throw exception;
//            }
//            if (value < volume) {// 如果Value小于容量则继续等待其他弧的汇聚。 (哪些状态为dead的token到此结束，不再向下传递)
//                return;  
//            }
//        }
//        //如果汇聚点的容量和同步器节点的容量相同
//        IProcessInstance processInstance = tk.getCurrentProcessInstance();
//        // Synchronize的fire条件应该只与joinPoint的value有关（value==volume），与alive无关
//        NodeEvent event2 = new NodeEvent(this);
//        event2.setToken(tk);
//        event2.setEventType(NodeEvent.NODEINSTANCE_FIRED);
//        fireNodeEvent(event2);
//
//        //在此事件监听器中，删除原有的token
//        NodeEvent event4 = new NodeEvent(this);
//        event4.setToken(tk);
//        event4.setEventType(NodeEvent.NODEINSTANCE_LEAVING);
//        fireNodeEvent(event4);
//
//        //首先必须检查是否有满足条件的循环，loop比transition有更高的优先级，
//        //（只能够有一个loop的条件为true，流程定义的时候需要注意）
//        boolean doLoop = false;//表示是否有满足条件的循环，false表示没有，true表示有。
//        if (joinPoint.getAlive()) {
//            IToken tokenForLoop = new Token(); // 产生新的token
//            tokenForLoop.setAlive(joinPoint.getAlive());
//            tokenForLoop.setCurrentProcessInstance(processInstance);
//            tokenForLoop.setStepNumber(joinPoint.getStepNumber()-1);
//            tokenForLoop.setFromActivityId(joinPoint.getFromActivityId());
//
//            for (int i = 0; i < this.leavingLoopInstances.size(); i++) {
//                ILoop loopInstance = this.leavingLoopInstances.get(i);
//                doLoop = loopInstance.take(tokenForLoop);
//                if (doLoop) {
//                    break;
//                }
//            }
//        }
//        if (!doLoop) {//如果没有循环，则执行transitionInstance
//                //非顺序流转的需要生成新的token，
//                boolean activiateDefaultCondition = true;
//                ITransition defaultTransInst = null;
//                for (int i = 0; leavingTransitionInstances != null && i < leavingTransitionInstances.size(); i++) {
//                    ITransition transInst = leavingTransitionInstances.get(i);
//                    String condition = transInst.getTransition().getCondition();
//                    if (condition != null && condition.equals(ConditionConstant.DEFAULT)) {
//                        defaultTransInst = transInst;
//                        continue;
//                    }
//
//                    Token token = new Token(); // 产生新的token
//                    token.setAlive(joinPoint.getAlive());
//                    token.setCurrentProcessInstance(processInstance);
//                    token.setStepNumber(joinPoint.getStepNumber());
//                    token.setFromActivityId(joinPoint.getFromActivityId());
//                    boolean alive = transInst.take(token);
//                    if (alive) {
//                        activiateDefaultCondition = false;
//                    }
//
//                }
//                if (defaultTransInst != null) {
//                    Token token = new Token();
//                    token.setAlive(activiateDefaultCondition && joinPoint.getAlive());
//                    token.setCurrentProcessInstance(processInstance);
//                    token.setStepNumber(joinPoint.getStepNumber());
//                    token.setFromActivityId(joinPoint.getFromActivityId());  
//                    defaultTransInst.take(token);
//                }
//            
//        }
//
//        NodeEvent event3 = new NodeEvent(this);
//        event3.setToken(tk);
//        event3.setEventType(NodeEvent.NODEINSTANCE_COMPLETED); //触发同步器节点的监听事件，删除所有和同步器节点相关的token
//        fireNodeEvent(event3);
//    }

    public void setVolume(int arg) {
        volume = arg;
    }

    public int getVolume() {
        return volume;
    }

    public String getExtensionTargetName() {
        return Extension_Target_Name;
    }

    public List<String> getExtensionPointNames() {
        return Extension_Point_Names;
    }

    // TODO extesion是单态还是多实例？单态应该效率高一些。
    public void register(INodeNetExtension extension)
            throws RuntimeException {
        if (!Extension_Target_Name.equals(extension.getExtentionTargetName())) {
            throw new RuntimeException(
                    "Error:When construct the SynchronizerInstance,the Extension_Target_Name is mismatching");
        }
        if (Extension_Point_NodeInstanceEventListener.equals(extension.getExtentionPointName())) {
            if (extension instanceof INodeEventListener) {
                this.eventListeners.add((INodeEventListener) extension);
            } else {
                throw new RuntimeException(
                        "Error:When construct the SynchronizerInstance,the extension MUST be a instance of INodeInstanceEventListener");
            }
        }
    }

    @Override
    public String toString() {
        return "SynchronizerInstance_4_[" + routerModel.getId() + "]";
    }
}
